package com.anlu.comet.emitter;

import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

/**
 * 全称：Server Send Event
 其实严格地说，HTTP 协议无法做到服务器主动推送数据到客户端的。只不过可以变通一下，
 就是服务器向客户端声明，接下来要发送的是流数据（stream）。
 此时，客户端不会关闭连接，会一直等着服务器发过来的新的数据流。
 SSE 就是利用这种机制，使用流信息向浏览器推送信息。它基于 HTTP 协议，
 目前除了 IE，其他浏览器都支持。
 IE的话，也可以通过evensource.js来兼容起来。
 */
@Controller
public class SseController {
    private static org.slf4j.Logger logger = LoggerFactory.getLogger(SseController.class);

    private static Map<String,SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();

    private ExecutorService executorService = Executors.newFixedThreadPool(2);
    @RequestMapping("/weChatPay")
    public String stock(){
        return "weChatPay";
    }

    @RequestMapping(value="/payMoney")
    @ResponseBody
    public SseEmitter pay(String weCharId){
        SseEmitter emitter = new SseEmitter();
        sseEmitterMap.put(weCharId,emitter);
        executorService.submit(new Pay(weCharId));
        return emitter;
    }

    private static class Pay implements Runnable{

        private String weCharId;

        public Pay(String weCharId) {
            this.weCharId = weCharId;
        }

        @Override
        public void run() {
            SseEmitter sseEmitter = sseEmitterMap.get(weCharId);
            try {
                logger.info("联系支付服务，准备扣款");
                Thread.sleep(500);
                sseEmitter.send("支付完成");
                logger.info("准备通知自动售货机");
                Thread.sleep(1500);//售货机的动作
                sseEmitter.send("已通知自动售货机C9出货，请勿走开！");
                sseEmitter.complete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
